package JUC.CountDownLatch和cyclicBarrier和Semaphore的使用;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * @author CKC
 * @DateTime 2021/3/31 20:01
 * <p>
 * <p>
 * 应用场景：
 * *    1.使用Semaphore限流，在访问高峰期时，让请求线程阻塞，高峰期过去在释放许可；他只适合
 * ×        限制单机线程数量，并且仅是限制线程数量 ，而不是限制资源数
 * ×    2.使用Semaphore实现简单连接池，对比『享元模式』下的实现（用wait notify),
 * *        性能和可读性显然更好
 */
@SuppressWarnings("all")
public class SemaphoreDemo  {
    public static void main(String[] args) throws Exception{
        Semaphore semaphore = new Semaphore(3);//模拟三个车位
        for (int i = 1; i <= 6; i++) {//模拟6部车
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    /**
                     * 从此信号量获取许可，直到获得一个许可或线程被中断为止，才进行许可。
                     * 如果有许可证，则获取许可证并立即返回，从而将可用许可证的数量减少一个。
                     * 如果没有可用的许可，则出于线程调度的目的，当前线程将被禁用，并处于休眠状态，直到发生以下两种情况之一：
                     * 其他一些线程为此信号量调用release方法，接下来将为当前线程分配一个许可；否则，将为当前线程分配一个许可。 或者
                     * 其他一些线程中断当前线程。
                     * 如果当前线程：
                     * 在进入此方法时已设置其中断状态； 或者
                     * 在等待许可证时被打断
                     *
                     */
                    System.out.println(Thread.currentThread().getName() + "\t抢到车位");

                    try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }

                    System.out.println(Thread.currentThread().getName() + "\t停车3秒钟后车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    /**
                     * 释放许可证，将其返回到信号灯。
                     * 发放许可证，将可用许可证数量增加一个。 如果有任何线程试图获取许可，则选择一个线程并授予刚刚释放的许可。 出于线程调度目的而启用（重新）该线程。
                     * 不要求释放许可证的线程必须已经通过调用acquire了该许可证。 信号量的正确用法是通过应用程序中的编程约定建立的。
                     */
                    semaphore.release();
                }
            }, String.valueOf(i)).start();

        }
    }
}
